package com.easipass.unifiedconfig.unic;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.TreeMap;

import com.easipass.unifiedconfig.NotFoundException;
import com.easipass.unifiedconfig.Parameter;
import com.easipass.unifiedconfig.ParametersTraverser;
import com.easipass.unifiedconfig.UCI;
import com.easipass.unifiedconfig.NotFoundException.Part;
import com.easipass.unifiedconfig.Parameter.AccessLevel;
import com.easipass.unifiedconfig.core.Authentication;

/**
 * 
 * @version $Id$
 * @author itea
 * @date 2010-1-19
 */
public class AccountRepo {

	protected final String account;
	
	protected Map<String, ModuleRepo> moduleIdx = Collections.synchronizedMap(new TreeMap<String, ModuleRepo>());
	
	protected static final String DEFUALT_MODULE = "<DEFUALT_MODULE>";
	
	public AccountRepo(String account) {
		this.account = account;
		moduleIdx.put(DEFUALT_MODULE, new ModuleRepo(null));
	}

	public Parameter getParameter(UCI uci) throws NotFoundException{
		if(!uci.matchesAccount(account))
			throw new NotFoundException(Part.ACCOUNT, uci);
		ModuleRepo mr = moduleIdx.get(getModuleName(uci.getModule()));
		if(mr == null)
			throw new NotFoundException(Part.MODULE, uci);
		return mr.getParameter(uci);
	}
	
	public void setParameter(Parameter p) throws NotFoundException {
		UCI uci = p.getUci();
		if(!uci.matchesAccount(account))
			throw new NotFoundException(Part.ACCOUNT, uci);
		ModuleRepo mr = moduleIdx.get(getModuleName(uci.getModule()));
		if(mr == null)
			mr = createModuleRepo(uci.getModule());
		mr.setParameter(p);
	}
	
	public void removeParameter(UCI uci) throws NotFoundException {
		if(!uci.matchesAccount(account))
			throw new NotFoundException(Part.ACCOUNT, uci);
		ModuleRepo mr = moduleIdx.get(getModuleName(uci.getModule()));
		if(mr == null)
			throw new NotFoundException(Part.MODULE, uci);
		else
			mr.removeParameter(uci);
	}
	
	public boolean containsParameter(UCI uci) {
		if(!uci.matchesAccount(account))
			return false;
		ModuleRepo mr = moduleIdx.get(getModuleName(uci.getModule()));
		if(mr == null)
			return false;
		else
			return mr.containsParameter(uci);
	}
	
	public void traverseParameters(Authentication a, UCI range, ParametersTraverser traverser) {
		for(ModuleRepo mr : moduleIdx.values())
			mr.traverseParameters(a, range, traverser);
	}
	
	public ModuleRepo getModuleRepo(String module) {
		return moduleIdx.get(module);
	}
	
	public ModuleRepo createModuleRepo(String module) {
		return createModuleRepo(module, AccessLevel.PUBLIC);
	}
	
	public synchronized ModuleRepo createModuleRepo(String module, AccessLevel defualtAccessLevel) {
		ModuleRepo mr = moduleIdx.get(getModuleName(module));
		if(mr == null){
			mr = new ModuleRepo(module, defualtAccessLevel);
			moduleIdx.put(module, mr);
		}
		return mr;
	}
	
	public void removeModuleRepo(String module) {
		moduleIdx.remove(module);
	}
	
	public Collection<UCI> listParameters(UCI range) {
		if(!range.matchesAccount(account))
			return Collections.emptyList();
			
		LinkedHashSet<UCI> ucis = new LinkedHashSet<UCI>();
		for(ModuleRepo mr : moduleIdx.values())
			ucis.addAll(mr.listParameters(range));
		return ucis;
	}
	
	protected static String getModuleName(String m) {
		return m == null ? DEFUALT_MODULE : m;
	}

	public String getAccount() {
		return account;
	}

}
